import { defineStore } from "pinia";
import { sStorage } from "@/utils";
import { router } from "@/router";
import {
  RouteLocationNormalizedLoaded as RouteLNL,
  RouteRecordNormalized as RouteRN,
  RouteMeta,
} from "vue-router";

interface TabPosition {
  left: number;
  top: number;
}

export interface TabRoute {
  name: string;
  path: string;
  scrollPos: TabPosition;
  // type RouteMeta = { title: string; icon: string };
  meta: RouteMeta & Sys.RouteMeta;
}

export const useTabStore = defineStore("tabStore", () => {
  const tabs = ref<TabRoute[]>([]);
  const activeTabPath = ref("");
  const homeTab = ref<TabRoute>({
    name: "root",
    path: "/",
    meta: {
      title: "Root",
    },
    scrollPos: {
      left: 0,
      top: 0,
    },
  });

  const activeTabIndex = computed(() => getIndexInTabs(activeTabPath.value));

  const activeTab = computed(() => tabs.value[activeTabIndex.value]);

  // route转tab
  const route2Tab = (route: RouteLNL | RouteRN | Sys.Route): TabRoute => {
    const fullPath = (route as RouteLNL).fullPath || route.path;
    return {
      name: route.name as string,
      path: fullPath,
      meta: route.meta as RouteMeta,
      scrollPos: {
        left: 0,
        top: 0,
      },
    };
  };

  // 添加tab
  const addTab = (route: RouteLNL) => {
    const tab = route2Tab(route);

    // 判断该tab是否已存在
    if (getIndexInTabs(tab.path) > -1) return;

    const index = getIndexByRouteName(tabs.value, route.name as string);

    if (index === -1) {
      tabs.value.push(tab);
    }
  };

  // 初始化首页页签路由
  const initHomeTab = (routes: Sys.Route[]) => {
    const findHome = getLeafRouter(routes);
    homeTab.value = route2Tab(findHome);
  };

  // 获取该页签在多页签数据中的索引
  const getIndexInTabs = (fullPath: string) => {
    return tabs.value.findIndex((tab) => tab.path == fullPath);
  };

  // 通过路由名获取该页签在多页签数据中的索引
  const getIndexByRouteName = (tabs: TabRoute[], routeName: string) => {
    return tabs.findIndex((tab) => tab.name === routeName);
  };

  // 重置tab状态
  const resetTabStore = () => {
    useTabStore().$reset();
    sStorage.set("multiTabRoutes", []);
  };

  // 缓存tabs
  const cacheTabRoutes = () => {
    sStorage.set("multiTabRoutes", tabs.value);
  };

  // 从缓存中获取tabs
  const getCacheTabRoutes = (): TabRoute[] => {
    const data: TabRoute[] = sStorage.get("multiTabRoutes") || [];
    return data.map((item) => ({
      ...item,
      scrollPos: {
        left: 0,
        top: 0,
      },
    }));
  };

  // 切换tab
  const setActiveTab = (fullPath: string) => {
    activeTabPath.value = fullPath;
  };

  // 删除tab
  const removeTab = async (fullPath: string) => {
    const isActive = activeTabPath.value === fullPath;
    const updateTabs = tabs.value.filter((tab) => tab.path !== fullPath);
    if (!isActive) tabs.value = updateTabs;
    if (isActive && updateTabs.length) {
      const tabIndex = getIndexInTabs(fullPath);
      const activePath = updateTabs[tabIndex - 1].path;
      const navigationFailure = await router.push(activePath);
      if (!navigationFailure) {
        tabs.value = updateTabs;
        setActiveTab(activePath);
      }
    }
  };

  /**
   * 清空tabs，只保留首页
   * @param excludes - 保留的多页签path
   */
  const clearTab = async (excludes: string[] = []) => {
    const homePath = homeTab.value?.path;
    const remain = [homePath, ...excludes];
    const hasActive = remain.includes(activeTabPath.value);
    const updateTabs = tabs.value.filter((tab) => remain.includes(tab.path));
    if (hasActive) tabs.value = updateTabs;
    if (!hasActive && updateTabs.length) {
      const activePath = updateTabs[updateTabs.length - 1].path;
      const navigationFailure = await router.push(activePath);
      if (!navigationFailure) {
        tabs.value = updateTabs;
        setActiveTab(activePath);
      }
    }
  };

  // 清除左边tabs
  const clearLeftTab = (fullPath: string) => {
    const index = getIndexInTabs(fullPath);
    if (index > -1) {
      const excludes = tabs.value.slice(index).map((item) => item.path);
      clearTab(excludes);
    }
  };

  // 清除右边tabs
  const clearRightTab = (fullPath: string) => {
    const index = getIndexInTabs(fullPath);
    if (index > -1) {
      const excludes = tabs.value.slice(0, index + 1).map((item) => item.path);
      clearTab(excludes);
    }
  };

  // 点击tab
  const handleClickTab = async (fullPath: string) => {
    const isActive = activeTabPath.value === fullPath;
    if (!isActive) {
      const navigationFailure = await router.push(fullPath);
      if (!navigationFailure) setActiveTab(fullPath);
    }
  };

  // 记录tab滚动位置
  const recordTabScrollPos = (fullPath: string, position: TabPosition) => {
    const index = getIndexInTabs(fullPath);
    if (index > -1) {
      tabs.value[index].scrollPos = position;
    }
  };

  // 获取tab滚动位置
  const getTabScrollPos = (fullPath: string) => {
    const position = { left: 0, top: 0 };
    const index = getIndexInTabs(fullPath);
    if (index > -1) {
      Object.assign(position, tabs.value[index].scrollPos);
    }
    return position;
  };

  // 初始化Tab状态
  const iniTabStore = (currentRoute: RouteLNL) => {
    const originTabs: TabRoute[] = getCacheTabRoutes();

    const hasHome = getIndexByRouteName(originTabs, homeTab.value!.name) > -1;
    if (!hasHome && homeTab.value!.name !== "root") {
      originTabs.unshift(homeTab.value!);
    }

    const isHome = currentRoute.fullPath === homeTab.value!.path;
    const index = getIndexByRouteName(originTabs, currentRoute.name as string);
    if (!isHome) {
      const currentTab = route2Tab(currentRoute);
      if (!currentRoute.meta.multiTab) {
        if (index > -1) {
          originTabs.splice(index, 1, currentTab);
        } else {
          originTabs.push(currentTab);
        }
      } else {
        const hasCurrent = getIndexInTabs(currentRoute.fullPath) > -1;
        if (!hasCurrent) {
          originTabs.push(currentTab);
        }
      }
    }

    tabs.value = originTabs;
    setActiveTab(currentRoute.fullPath);
  };

  return {
    tabs,
    homeTab,
    activeTab,
    activeTabPath,
    activeTabIndex,
    addTab,
    setActiveTab,
    initHomeTab,
    iniTabStore,
    resetTabStore,
    cacheTabRoutes,
    removeTab,
    clearTab,
    clearLeftTab,
    clearRightTab,
    handleClickTab,
    getTabScrollPos,
    recordTabScrollPos,
  };
});

const getLeafRouter = (routes: Sys.Route[]): Sys.Route => {
  const firstChild = routes[0];

  if (firstChild.children && firstChild.children.length) {
    return getLeafRouter(firstChild.children);
  }
  return firstChild;
};
